#ifndef FEATURE_H
#define FEATURE_H
#include <assert.h>
#include "include/jpeglib.h"
#include "include/jpegint.h"
#include "include/jerror.h"
#include "../tools/jpeg_tool.h"
#include "../libsvm/svm.h"

int feature1D(char* input_name, double* hist, int t) {
	struct jpeg_decompress_struct srcinfo;
	struct jpeg_error_mgr srcjerr;
	jvirt_barray_ptr *srccoef_arrays;
	FILE *infile;
	int ci, i;
	long total = 0;

	assert(input_name);
	assert(hist);
	assert(t >= 0);
	if (((infile = fopen(input_name, "rb")) == NULL)) {
		fprintf(stderr,"Cannot open input / output file");
		return -3;
	}
	for (i = 0;i<2*t+1;i++)
		hist[i] = 0;

	jpeg_read_prepare(&srcinfo, &srcjerr, infile);
	srccoef_arrays = jpeg_read_coefficients(&srcinfo);

//	for (ci = 0;ci < srcinfo.num_components;ci++) {
	for (ci = 0;ci < 1;ci++) {
		JDIMENSION height, width, blk_x, blk_y;
		short p, i;
		JBLOCKARRAY srcbuffer;
		JCOEFPTR srcbufptr;

		height = srcinfo.comp_info[ci].height_in_blocks;
		width = srcinfo.comp_info[ci].width_in_blocks;
		for (blk_y = 0;blk_y < height;blk_y++) {
			srcbuffer = (srcinfo.mem->access_virt_barray)	((j_common_ptr) &srcinfo, srccoef_arrays[ci], blk_y, 1, FALSE);
			for (blk_x = 0;blk_x < width;blk_x++) {
				srcbufptr = srcbuffer[0][blk_x];
				for (i = 1;i < DCTSIZE2;i++) {
					p = (short)(srcbufptr[i]);
					if ((p <= t) && (p >= -t)) {
						hist[p+t] = hist[p+t]+1;
						total++;
					}
				}
			}
		}
	}
	jpeg_read_done(&srcinfo);
	fclose(infile);
	if (total > 0) {
		int i;
		for (i=0;i<2*t+1;i++) {
			hist[i] = hist[i] / total;
		}
	}
	return 0;
}

int _predictOne(char *model_name, char *feature_name, int feature_len, char *output_name) {
	FILE *fin = NULL;
	FILE *fout = NULL;
	struct svm_model *model;
	double *feature = NULL;
	int i, count;
	struct svm_node *x;
	double fval;
	double cls;
	int lbl, index;
	int clsnum;
	double *prob_estimates;

	assert(model_name && feature_name && output_name && (feature_len > 0));
	// load model
	model = svm_load_model(model_name);
	if (!model)
		return -2;

	fin = fopen(feature_name, "rt");
	if (!fin)
		return -3;

	feature = (double*) malloc((feature_len+1) * sizeof(double));
	x = (struct svm_node*) malloc((feature_len+1) * sizeof(struct svm_node));
	assert(feature && x);

	for (i = 0;i < feature_len;i++)
		feature[i] = 0.0;

	count = 0;
	(void) fscanf(fin, "%d", &lbl);
	while (1) {
		char buf[1000];
		int ret = fscanf(fin, "%s", buf);
		if (ret > 0) {
			char* val;
			char* idx;
			idx = strtok(buf,":");
			val = strtok(NULL,":");
			assert(idx);
			assert(val);
			index=atoi(idx);
			fval=atof(val);
		}
		//ret = fscanf(fin, "%d:%0.4f", &index, &fval);
		if ((ret > 0) && (index <= feature_len) && (index > 0)) {
			feature[index] = fval;
			count++;
		}
		else
			break;
		if (count >= feature_len)
			break;
	}
	// construct svm_node
	for (i = 0;i < feature_len;i++) {
		x[i].index = i+1;
		x[i].value = feature[i+1];
	}
	x[feature_len].index = -1;

	/*
	if (svm_check_probability_model(model))
		fprintf(ftest,"probability model\n");
	else
		fprintf(ftest,"not probability model\n");
	*/

	clsnum = svm_get_nr_class(model);
	prob_estimates = (double*) malloc(clsnum*sizeof(double));
	assert(prob_estimates);
	for (i=0;i<clsnum;i++)
		prob_estimates[i] = 0;

	fout = fopen(output_name, "wt");
	if (!fout)
		return -3;
	
	cls = svm_predict_probability(model, x, prob_estimates);
	fprintf(fout, "%d\n",cls);

	for (i=0;i<clsnum;i++) {
		fprintf(fout, "%d : %0.4f\n",i, prob_estimates[i]);
	}

	fclose(fin);
	fclose(fout);
	free(feature);
	free(prob_estimates);
	free(x);
	svm_free_and_destroy_model(&model);
	return cls;
}

#endif 